package billingServer;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Group 95
 */
public class PriceSteps implements Serializable {

    private static final String NEW_LINE = System.getProperty("line.separator");
    private static final Logger logger = Logger.getLogger("PriceSteps");
    private static String LISTHEADER =
            "Min_Price" + "\t"
            + "Max_Price" + "\t"
            + "Fee_Fixed" + "\t"
            + "Fee_Variable";
    private ArrayList<PriceStep> priceSteps;

    public PriceSteps() {
        logger.setLevel(Level.OFF);
        priceSteps = new ArrayList<PriceStep>();
    }

    /**
     * Adds a new PriceStep. Returns false if paramenters for new step are
     * invalid (negative) or new step would collide with existing one.
     *
     * @param startPrice
     * @param endPrice
     * @param fixedPrice
     * @param variablePricePercent
     * @return false if parameters for new step are invalid or new step would collide with existing
     */
    public synchronized boolean addStep(double startPrice, double endPrice, double fixedPrice, double variablePricePercent) {
        //@todo: Kollision mit bestehenden steps prüfen
        logger.log(Level.INFO, "Add new PriceStep: {0} {1}", new Object[]{startPrice, endPrice});
        if (startPrice < 0 || endPrice < 0 || fixedPrice < 0 || variablePricePercent < 0 || startPrice>=endPrice) {
            System.out.println("Add new PriceStep, negative parameters: " + startPrice + " "
                    + endPrice + " "
                    + fixedPrice + " "
                    + variablePricePercent + " .");
            return false;
        }
        PriceStep curStep=null;
        if (!getPriceSteps().isEmpty()) {
            final ListIterator<PriceStep> iterator = getPriceSteps().listIterator();
            
            while (iterator.hasNext()) {
                curStep = iterator.next();
                logger.log(Level.INFO, "PriceStep: {0} {1}", new Object[]{curStep.getStartPrice(), curStep.getEndPrice()});
                if(curStep.getEndPrice()<= startPrice)
                {
                    getPriceSteps().add(iterator.nextIndex(), new PriceStep(startPrice, endPrice, fixedPrice, variablePricePercent));
                    return true;
                }
            }
        }
        else
        {
            getPriceSteps().add(new PriceStep(startPrice, endPrice, fixedPrice, variablePricePercent));
            return true;
        }
        return false;
    }

    /**
     * Remove a PriceStep. Return false if the requested step does not exist.
     *
     * @param startPrice
     * @param endPrice
     * @return
     */
    public synchronized boolean removeStep(final double startPrice, final double endPrice) {
        int counter = 0;
        if (!getPriceSteps().isEmpty()) {
            final Iterator<PriceStep> iterator = getPriceSteps().iterator();
            PriceStep curStep;
            while (iterator.hasNext()) {
                curStep = iterator.next();
                logger.log(Level.INFO, "PriceStep: {0} {1}", new Object[]{curStep.getStartPrice(), curStep.getEndPrice()});
                if (curStep.getStartPrice() >= startPrice && curStep.getEndPrice() <= endPrice) {
                    iterator.remove();
                    counter++;
                } else if (endPrice < curStep.getEndPrice()) {
                    break;
                }
            }
        }
        return counter > 0;
    }

    /**
     * Create table-view of PriceSteps. One line for each step.
     *
     * @return
     */
    public String toLine() {
        final StringBuilder strB = new StringBuilder();
        if (getPriceSteps().size() < 1) {
            strB.append("No price steps set");

        } else {
            strB.append(LISTHEADER);
            for (PriceStep p : getPriceSteps()) {
                strB.append(NEW_LINE).append(p.toLine());
            }
        }
        return strB.toString();
    }

    /**
     * @return the priceSteps
     */
    public List<PriceStep> getPriceSteps() {
        return priceSteps;
    }
}
